{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "📋 Notebook configured to use: claude-opus-4-5\n"
     ]
    }
   ],
   "source": [
    "from dotenv import load_dotenv\n",
    "from utils.agent_visualizer import (\n",
    "    display_agent_response,\n",
    "    print_activity,\n",
    "    reset_activity_context,\n",
    "    visualize_conversation,\n",
    ")\n",
    "\n",
    "from claude_agent_sdk import ClaudeAgentOptions, ClaudeSDKClient\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "# Define the model to use throughout this notebook\n",
    "# Using Opus 4.5 for its superior planning and reasoning capabilities\n",
    "MODEL = \"claude-opus-4-5\"\n",
    "print(f\"📋 Notebook configured to use: {MODEL}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 01 - The Chief of Staff Agent\n",
    "\n",
    "#### Introduction\n",
    "\n",
    "In notebook 00, we built a simple research agent. In this notebook, we'll incrementally introduce key Claude Code SDK features for building comprehensive agents. For each introduced feature, we'll explain:\n",
    "- **What**: what the feature is\n",
    "- **Why**: what the feature can do and why you would want to use it\n",
    "- **How**: a minimal implementation showing how to use it\n",
    "\n",
    "If you are familiar with Claude Code, you'll notice how the SDK brings feature parity and enables you to leverage all of Claude Code's capabilities in a programmatic headless manner.\n",
    "\n",
    "#### Scenario\n",
    "\n",
    "Throughout this notebook, we'll build an **AI Chief of Staff** for a 50-person startup that just raised $10M Series A. The CEO needs data-driven insights to balance aggressive growth with financial sustainability.\n",
    "\n",
    "Our final Chief of Staff agent will:\n",
    "- **Coordinate specialized subagents** for different domains\n",
    "- **Aggregate insights** from multiple sources\n",
    "- **Provide executive summaries** with actionable recommendations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic Features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 0: Memory with [CLAUDE.md](https://www.anthropic.com/engineering/claude-code-best-practices)\n",
    "\n",
    "**What**: `CLAUDE.md` files serve as persistent memory and instructions for your agent. When present in the project directory, Claude Code automatically reads and incorporates this context when you initialize your agent.\n",
    "\n",
    "**Why**: Instead of repeatedly providing project context, team preferences, or standards in each interaction, you can define them once in `CLAUDE.md`. This ensures consistent behavior and reduces token usage by avoiding redundant explanations.\n",
    "\n",
    "**How**: \n",
    "- Have a `CLAUDE.md` file in the working directory - in our example: `chief_of_staff_agent/CLAUDE.md`\n",
    "- Set the `cwd` argument of your ClaudeSDKClient to point to directory of your CLAUDE.md file\n",
    "- Use explicit prompts to guide the agent when you want it to prefer high-level context over detailed data files\n",
    "\n",
    "**Important Behavior Note**: When both CLAUDE.md and detailed data files (like CSVs) are available, the agent may prefer to read the more granular data sources to provide precise answers. This is expected behavior - agents naturally seek authoritative data. To ensure the agent uses high-level CLAUDE.md context, use explicit prompt instructions (see example below). This teaches an important lesson: CLAUDE.md provides *context and guidance*, not hard constraints on data sources."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Thinking...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Agent Response</div><p>Based on the company information, <strong>TechStart Inc's current runway is 20 months</strong> (until September 2025).</p>\n",
       "<p>Here are the key financial details:<br />\n",
       "- <strong>Cash in Bank</strong>: $10M<br />\n",
       "- <strong>Monthly Burn Rate</strong>: ~$500,000<br />\n",
       "- <strong>Runway</strong>: 20 months</p>\n",
       "<p>This gives you a solid runway to execute on Q2 2024 priorities, including hiring 10 engineers, launching the AI code review feature, European expansion, and beginning Series B conversations (targeting $30M).</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "messages = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        cwd=\"chief_of_staff_agent\",  # Points to subdirectory with our CLAUDE.md\n",
    "        setting_sources=[\"project\"],\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\"What's our current runway?\")\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages.append(msg)\n",
    "\n",
    "# Display the response with HTML rendering\n",
    "display_agent_response(messages)\n",
    "# With this prompt, the agent should use CLAUDE.md values: ~$500K burn, 20 months runway"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Understanding Agent Data Source Preferences\n",
    "\n",
    "**What Just Happened:**\n",
    "By adding   to our prompt, we guided the agent to rely on the CLAUDE.md context rather than seeking more granular data from CSV files.\n",
    "\n",
    "**Key Insights:**\n",
    "1. **CLAUDE.md as Context, Not Constraint**: When you set `cwd`, the CLAUDE.md file is loaded as background context. However, agents will naturally seek the most authoritative data sources available. If detailed CSV files exist, the agent may prefer them for precision.\n",
    "\n",
    "2. **Prompt Engineering Matters**: The phrasing \"high-level financial numbers from context\" signals to the agent that you want the simplified executive summary from CLAUDE.md ($500K burn, 20 months runway) rather than the precise month-by-month data from financial_data/burn_rate.csv ($525K gross, $235K net burn).\n",
    "\n",
    "3. **Architectural Design Choice**: This behavior is actually desirable in production systems - you want agents to find the best data source. CLAUDE.md should contain:\n",
    "   - High-level context and strategy\n",
    "   - Company information and standards\n",
    "   - Pointers to where detailed data lives\n",
    "   - Guidelines on when to use high-level vs. detailed numbers\n",
    "\n",
    "4. **Real-World Pattern**: Think of CLAUDE.md as an \"onboarding document\" that orients the agent, while detailed files are \"source systems\" the agent can query when precision matters."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 1: The Bash tool for Python Script Execution\n",
    "\n",
    "**What**: The Bash tool allows your agent to (among other things) run Python scripts directly, enabling access to procedural knowledge, complex computations, data analysis and other integrations that go beyond the agent's native capabilities.\n",
    "\n",
    "**Why**: Our Chief of Staff might need to process data files, run financial models or generate visualizations based on this data. These are all good scenarios for using the Bash tool.\n",
    "\n",
    "**How**: Have your Python scripts set-up in a place where your agent can reach them and add some context on what they are and how they can be called. If the scripts are meant for your chief of staff agent, add this context to its CLAUDE.md file and if they are meant for one your subagents, add said context to their MD files (more details on this later). For this tutorial, we added five toy examples to `chief_of_staff_agent/scripts`:\n",
    "1. `hiring_impact.py`: Calculates how new engineering hires affect burn rate, runway, and cash position. Essential for the `financial-analyst` subagent to model hiring scenarios against the $500K monthly burn and 20-month runway.\n",
    "2. `talent_scorer.py`: Scores candidates on technical skills, experience, culture fit, and salary expectations using weighted criteria. Core tool for the `recruiter` subagent to rank engineering candidates against TechStart's $180-220K senior engineer benchmarks.\n",
    "3. `simple_calculation.py`: Performs quick financial calculations for runway, burn rate, and quarterly metrics. Utility script for chief of staff to get instant metrics without complex modeling.\n",
    "4. `financial_forecast.py`: Models ARR growth scenarios (base/optimistic/pessimistic) given the current $2.4M ARR growing at 15% MoM.Critical for `financial-analyst` to project Series B readiness and validate the $30M fundraising target.\n",
    "5. `decision_matrix.py`: Creates weighted decision matrices for strategic choices like the SmartDev acquisition or office expansion. Helps chief of staff systematically evaluate complex decisions with multiple stakeholders and criteria."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Using: Glob()\n",
      "🤖 Using: Glob()\n",
      "🤖 Using: Glob()\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n",
      "🤖 Using: Read()\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n",
      "🤖 Using: Bash()\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Agent Response</div><p>Here are the financial metrics calculated using the simple calculation script:</p>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Metric</th>\n",
       "<th>Value</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td><strong>Total Runway</strong></td>\n",
       "<td>$2,904,829.00</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Monthly Burn</strong></td>\n",
       "<td>$121,938.00</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Runway Months</strong></td>\n",
       "<td>~23.82 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Quarterly Burn</strong></td>\n",
       "<td>$365,814.00</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Daily Burn Rate</strong></td>\n",
       "<td>$4,064.60</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<p>Based on these calculations, with a total runway of $2,904,829 and a monthly burn rate of $121,938, you have approximately <strong>23.8 months</strong> (just under 2 years) of runway remaining.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "messages = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        allowed_tools=[\"Bash\", \"Read\"],\n",
    "        cwd=\"chief_of_staff_agent\",  # Points to subdirectory where our agent is defined\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\n",
    "        \"Use your simple calculation script with a total runway of 2904829 and a monthly burn of 121938.\"\n",
    "    )\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages.append(msg)\n",
    "\n",
    "# Display the response with HTML rendering\n",
    "display_agent_response(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 2: Output Styles\n",
    "\n",
    "**What**: Output styles allow you to use different output styles for different audiences. Each style is defined in a markdown file.\n",
    "\n",
    "**Why**: Your agent might be used by people of different levels of expertise or they might have different priorities. Your output style can help differentiate between these segments without having to create a separate agent.\n",
    "\n",
    "**How**:\n",
    "- Configure a markdown file per style in `chief_of_staff_agent/.claude/output-styles/`. For example, check out the Executive Ouput style in `.claude/output-styles/executive.md`. Output styles are defined with a simple frontmatter including two fields: name and description. Note: Make sure the name in the frontmatter matches exactly the file's name (case sensitive)\n",
    "\n",
    "> **IMPORTANT**: Output styles modify the system prompt that Claude Code has underneath, leaving out the parts focused on software engineering and giving you more control for your specific use case beyond software engineering work.\n",
    "\n",
    "> **SDK CONFIGURATION NOTE**: Similar to slash commands (covered in Feature 4), output styles are stored on the filesystem in `.claude/output-styles/`. For the SDK to load these files, you **must** include `setting_sources=[\"project\"]` in your `ClaudeAgentOptions`. The `settings` parameter tells the SDK *which* style to use, but `setting_sources` is required to actually *load* the style definitions. This requirement was identified while debugging later sections and applies to all filesystem-based settings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Thinking...\n",
      "🤖 Thinking...\n"
     ]
    }
   ],
   "source": [
    "messages_executive = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        cwd=\"chief_of_staff_agent\",\n",
    "        settings='{\"outputStyle\": \"executive\"}',\n",
    "        # IMPORTANT: setting_sources must include \"project\" to load output styles from .claude/output-styles/\n",
    "        # Without this, the SDK does NOT load filesystem settings (output styles, slash commands, etc.)\n",
    "        setting_sources=[\"project\"],\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\"Tell me in two sentences about your writing output style.\")\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages_executive.append(msg)\n",
    "\n",
    "messages_technical = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        cwd=\"chief_of_staff_agent\",\n",
    "        settings='{\"outputStyle\": \"technical\"}',\n",
    "        setting_sources=[\"project\"],\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\"Tell me in two sentences about your writing output style.\")\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages_technical.append(msg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Agent Response</div><p>My writing style is direct, concise, and professional—I avoid unnecessary filler and get straight to actionable insights. I adapt my tone based on context: more formal for strategic recommendations and board-level communications, more conversational for quick operational questions.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Display executive style response\n",
    "display_agent_response(messages_executive)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Technical Style</div><p>My writing style is direct, clear, and professional—I provide concise answers without unnecessary filler while ensuring the information is complete and actionable. I adapt my tone to the context, being more formal for business analysis and more conversational for general questions, and I use formatting (like bullet points, headers, or code blocks) when it helps organize complex information.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Technical output style - detailed, implementation-focused\n",
    "display_agent_response(messages_technical, title=\"Technical Style\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 3: Plan Mode - Strategic Planning Without Execution\n",
    "\n",
    "**What**: Plan mode instructs the agent to create a detailed execution plan without performing any actions. The agent analyzes requirements, proposes solutions, and outlines steps, but doesn't modify files, execute commands, or make changes.\n",
    "\n",
    "**Why**: Complex tasks benefit from upfront planning to reduce errors, enable review and improve coordination. After the planning phase, the agent will have a red thread to follow throughout its execution.\n",
    "\n",
    "**How**: Just set `permission_mode=\"plan\"`\n",
    "\n",
    "**Plan Persistence**: Since plans are valuable artifacts for review and decision-making, we'll demonstrate how to capture and save them to persistent markdown files. This enables stakeholders to review plans before approving execution.\n",
    "\n",
    "> Note: this feature shines in Claude Code but still needs to be fully adapted for headless applications with the SDK. Namely, the agent will try calling its `ExitPlanMode()` tool, which is only relevant in the interactive mode. In this case, you can send up a follow-up query with `continue_conversation=True` for the agent to execute its plan in context."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ Plan Mode helper functions loaded\n"
     ]
    }
   ],
   "source": [
    "# =============================================================================\n",
    "# Plan Mode Helper Functions\n",
    "# =============================================================================\n",
    "# These utilities handle the various ways an agent might output its plan.\n",
    "# Since agents can output plans via direct text, Write tool, or Claude's\n",
    "# internal plan directory, we need robust extraction from multiple sources.\n",
    "\n",
    "import glob as glob_module\n",
    "import os\n",
    "import re\n",
    "from datetime import datetime\n",
    "from pathlib import Path\n",
    "from typing import Any\n",
    "\n",
    "\n",
    "def extract_plan_from_xml(text: str | None, min_length: int = 200) -> str | None:\n",
    "    \"\"\"\n",
    "    Extract content between <plan> tags from text.\n",
    "\n",
    "    Args:\n",
    "        text: The text to search for plan content\n",
    "        min_length: Minimum character count for valid plan (prevents empty matches)\n",
    "\n",
    "    Returns:\n",
    "        Extracted plan content, or None if not found/too short\n",
    "    \"\"\"\n",
    "    if not text:\n",
    "        return None\n",
    "    match = re.search(r\"<plan>(.*?)</plan>\", text, re.DOTALL)\n",
    "    if match:\n",
    "        extracted = match.group(1).strip()\n",
    "        if len(extracted) > min_length:\n",
    "            return extracted\n",
    "    return None\n",
    "\n",
    "\n",
    "def extract_plan_from_messages(\n",
    "    plan_content: list[str], min_fallback_length: int = 500\n",
    ") -> tuple[str | None, str | None]:\n",
    "    \"\"\"\n",
    "    Try to extract plan from captured message stream content.\n",
    "\n",
    "    Args:\n",
    "        plan_content: List of text blocks captured during streaming\n",
    "        min_fallback_length: Minimum length for fallback (no XML tags)\n",
    "\n",
    "    Returns:\n",
    "        Tuple of (plan_text, source_description)\n",
    "    \"\"\"\n",
    "    combined_text = \"\\n\\n\".join(plan_content)\n",
    "\n",
    "    # First try: XML tags\n",
    "    plan = extract_plan_from_xml(combined_text)\n",
    "    if plan:\n",
    "        return plan, \"message stream\"\n",
    "\n",
    "    # Fallback: Use raw content if substantial\n",
    "    if len(combined_text.strip()) > min_fallback_length:\n",
    "        return combined_text.strip(), \"full message content (fallback)\"\n",
    "\n",
    "    return None, None\n",
    "\n",
    "\n",
    "def extract_plan_from_write_tool(\n",
    "    write_contents: list[str], min_fallback_length: int = 500\n",
    ") -> tuple[str | None, str | None]:\n",
    "    \"\"\"\n",
    "    Try to extract plan from captured Write tool calls.\n",
    "\n",
    "    Args:\n",
    "        write_contents: List of content strings from Write tool calls\n",
    "        min_fallback_length: Minimum length for fallback (no XML tags)\n",
    "\n",
    "    Returns:\n",
    "        Tuple of (plan_text, source_description)\n",
    "    \"\"\"\n",
    "    for content in write_contents:\n",
    "        # Try XML extraction first\n",
    "        plan = extract_plan_from_xml(content)\n",
    "        if plan:\n",
    "            return plan, \"Write tool capture\"\n",
    "\n",
    "        # Fallback: substantial content without tags\n",
    "        if content and len(content.strip()) > min_fallback_length:\n",
    "            return content.strip(), \"Write tool capture (no XML tags)\"\n",
    "\n",
    "    return None, None\n",
    "\n",
    "\n",
    "def extract_plan_from_claude_dir(\n",
    "    max_age_seconds: int = 300, min_fallback_length: int = 500\n",
    ") -> tuple[str | None, str | None]:\n",
    "    \"\"\"\n",
    "    Check Claude's internal plan directory for recently created plans.\n",
    "\n",
    "    Args:\n",
    "        max_age_seconds: Maximum age of plan file to consider (default: 5 minutes)\n",
    "        min_fallback_length: Minimum length for fallback (no XML tags)\n",
    "\n",
    "    Returns:\n",
    "        Tuple of (plan_text, source_description)\n",
    "    \"\"\"\n",
    "    claude_plans_dir = os.path.expanduser(\"~/.claude/plans\")\n",
    "\n",
    "    if not os.path.exists(claude_plans_dir):\n",
    "        return None, None\n",
    "\n",
    "    # Find most recent plan file\n",
    "    plan_files = sorted(\n",
    "        glob_module.glob(os.path.join(claude_plans_dir, \"*.md\")),\n",
    "        key=os.path.getmtime,\n",
    "        reverse=True,\n",
    "    )\n",
    "\n",
    "    if not plan_files:\n",
    "        return None, None\n",
    "\n",
    "    most_recent = plan_files[0]\n",
    "    file_age = datetime.now().timestamp() - os.path.getmtime(most_recent)\n",
    "\n",
    "    if file_age > max_age_seconds:\n",
    "        return None, None\n",
    "\n",
    "    with open(most_recent) as f:\n",
    "        content = f.read()\n",
    "\n",
    "    filename = os.path.basename(most_recent)\n",
    "\n",
    "    # Try XML extraction first\n",
    "    plan = extract_plan_from_xml(content)\n",
    "    if plan:\n",
    "        return plan, f\"Claude plan file ({filename})\"\n",
    "\n",
    "    # Fallback: substantial content without tags\n",
    "    if len(content.strip()) > min_fallback_length:\n",
    "        return content.strip(), f\"Claude plan file ({filename}, no XML tags)\"\n",
    "\n",
    "    return None, None\n",
    "\n",
    "\n",
    "def save_plan_to_file(\n",
    "    plan_content: str,\n",
    "    plan_source: str,\n",
    "    model_name: str,\n",
    "    prompt_summary: str,\n",
    "    output_dir: str = \"chief_of_staff_agent/plans\",\n",
    "    title: str = \"Agent Plan: Engineering Restructure for AI Focus\",\n",
    ") -> Path:\n",
    "    \"\"\"\n",
    "    Save extracted plan to a timestamped markdown file.\n",
    "\n",
    "    Args:\n",
    "        plan_content: The plan text to save\n",
    "        plan_source: Description of where plan was extracted from\n",
    "        model_name: The model used to generate the plan\n",
    "        prompt_summary: Brief description of the original prompt\n",
    "        output_dir: Directory to save plan files\n",
    "        title: Title for the plan document\n",
    "\n",
    "    Returns:\n",
    "        Path to the saved plan file\n",
    "    \"\"\"\n",
    "    plans_dir = Path(output_dir)\n",
    "    plans_dir.mkdir(exist_ok=True)\n",
    "\n",
    "    timestamp = datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
    "    plan_file = plans_dir / f\"plan_{timestamp}.md\"\n",
    "\n",
    "    with open(plan_file, \"w\") as f:\n",
    "        f.write(f\"# {title}\\n\\n\")\n",
    "        f.write(f\"**Created:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\\n\")\n",
    "        f.write(f\"**Prompt:** {prompt_summary}\\n\")\n",
    "        f.write(f\"**Model:** {model_name}\\n\")\n",
    "        f.write(f\"**Plan Source:** {plan_source}\\n\\n\")\n",
    "        f.write(\"---\\n\\n\")\n",
    "        f.write(plan_content)\n",
    "        f.write(\"\\n\\n---\\n\\n\")\n",
    "        f.write(\"*This plan was generated in plan mode and has not been executed.*\\n\")\n",
    "\n",
    "    return plan_file\n",
    "\n",
    "\n",
    "def capture_message_content(\n",
    "    msg: Any,\n",
    "    plan_content: list[str],\n",
    "    write_tool_content: list[str],\n",
    "    write_tool_paths: list[str],\n",
    ") -> None:\n",
    "    \"\"\"\n",
    "    Process a streaming message and capture relevant plan content.\n",
    "\n",
    "    This function extracts content from three potential sources:\n",
    "    1. Text blocks in message content\n",
    "    2. Write tool call parameters\n",
    "    3. Final result attribute\n",
    "\n",
    "    Args:\n",
    "        msg: The message object from the agent stream\n",
    "        plan_content: List to append text content to\n",
    "        write_tool_content: List to append Write tool content to\n",
    "        write_tool_paths: List to append Write tool file paths to\n",
    "    \"\"\"\n",
    "    # Source 1: Text blocks from message content\n",
    "    if hasattr(msg, \"content\"):\n",
    "        for block in msg.content:\n",
    "            if hasattr(block, \"text\"):\n",
    "                plan_content.append(block.text)\n",
    "\n",
    "            # Source 2: Write tool calls\n",
    "            if hasattr(block, \"type\") and block.type == \"tool_use\":\n",
    "                if hasattr(block, \"name\") and block.name == \"Write\":\n",
    "                    if hasattr(block, \"input\") and isinstance(block.input, dict):\n",
    "                        if \"content\" in block.input:\n",
    "                            write_tool_content.append(block.input[\"content\"])\n",
    "                        if \"file_path\" in block.input:\n",
    "                            write_tool_paths.append(block.input[\"file_path\"])\n",
    "\n",
    "    # Source 3: Final result\n",
    "    if hasattr(msg, \"result\") and msg.result:\n",
    "        plan_content.append(msg.result)\n",
    "\n",
    "\n",
    "print(\"✅ Plan Mode helper functions loaded\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "📋 Plan Mode configured with model: claude-opus-4-5\n",
      "📝 Prompt length: 1,180 characters\n"
     ]
    }
   ],
   "source": [
    "# =============================================================================\n",
    "# Plan Mode Configuration\n",
    "# =============================================================================\n",
    "\n",
    "# Note: MODEL is defined in cell-0 as \"claude-opus-4-5\"\n",
    "# Opus excels at complex planning tasks\n",
    "\n",
    "# The prompt is carefully crafted to:\n",
    "# 1. Provide explicit context (since Opus prefers explicit information)\n",
    "# 2. Request XML-tagged output for reliable extraction\n",
    "# 3. Prevent file-writing so we can capture the plan programmatically\n",
    "\n",
    "PLAN_PROMPT = \"\"\"Restructure our engineering team for AI focus.\n",
    "\n",
    "**CONTEXT (from CLAUDE.md):**\n",
    "You are the Chief of Staff for TechStart Inc, a 50-person B2B SaaS startup that raised $10M Series A.\n",
    "- Current engineering team: 25 people (Backend: 12, Frontend: 8, DevOps: 5)\n",
    "- Monthly burn rate: ~$500K, Runway: 20 months\n",
    "- Senior Engineer compensation: $180K-$220K + equity\n",
    "\n",
    "**CRITICAL OUTPUT INSTRUCTIONS:**\n",
    "\n",
    "1. **DO NOT use the Write tool** - Output your plan directly in your response text\n",
    "2. **DO NOT save to any files** - I will handle saving the plan myself\n",
    "3. **Wrap your ENTIRE plan inside `<plan> </plan>` XML tags** in your response\n",
    "\n",
    "**Required Format:**\n",
    "<plan>\n",
    "[Your complete restructuring plan here - include all sections, timelines, budgets, and recommendations]\n",
    "</plan>\n",
    "\n",
    "**IMPORTANT:**\n",
    "- The plan content MUST appear directly in your response between the XML tags\n",
    "- Do NOT use Write, Edit, or any file-saving tools\n",
    "- You may research and analyze before outputting, but the final plan must be in your response text\n",
    "- Include: team structure, hiring recommendations, timeline, budget impact, and success metrics\n",
    "- Use the company context provided above - do NOT ask clarifying questions\"\"\"\n",
    "\n",
    "print(f\"📋 Plan Mode configured with model: {MODEL}\")\n",
    "print(f\"📝 Prompt length: {len(PLAN_PROMPT):,} characters\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Thinking...\n",
      "🤖 Using: ExitPlanMode()\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n",
      "\n",
      "✅ Agent completed. Captured 3 content blocks.\n"
     ]
    }
   ],
   "source": [
    "# =============================================================================\n",
    "# Execute Plan Mode Agent\n",
    "# =============================================================================\n",
    "# Run the agent with plan mode enabled. The agent will create a detailed plan\n",
    "# but won't execute any actions. We capture content from multiple sources\n",
    "# to handle different agent behaviors.\n",
    "\n",
    "# Initialize capture lists\n",
    "messages = []\n",
    "plan_content = []  # Text from message stream\n",
    "write_tool_content = []  # Content from Write tool calls\n",
    "write_tool_paths = []  # Paths from Write tool calls\n",
    "\n",
    "# Run the agent in plan mode\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        permission_mode=\"plan\",\n",
    "        cwd=\"chief_of_staff_agent\",\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(PLAN_PROMPT)\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages.append(msg)\n",
    "\n",
    "        # Capture content from this message\n",
    "        capture_message_content(msg, plan_content, write_tool_content, write_tool_paths)\n",
    "\n",
    "print(f\"\\n✅ Agent completed. Captured {len(plan_content)} content blocks.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ Plan extracted from: message stream\n",
      "   Plan length: 6,783 characters\n",
      "\n",
      "📁 Plan saved to: chief_of_staff_agent/plans/plan_20251204_152737.md\n"
     ]
    }
   ],
   "source": [
    "# =============================================================================\n",
    "# Extract and Save the Plan\n",
    "# =============================================================================\n",
    "# Try multiple sources in priority order to find the plan content.\n",
    "# This handles different agent behaviors robustly.\n",
    "\n",
    "final_plan = None\n",
    "plan_source = None\n",
    "\n",
    "# Priority 1: Message stream (preferred - direct from agent response)\n",
    "final_plan, plan_source = extract_plan_from_messages(plan_content)\n",
    "\n",
    "# Priority 2: Write tool captures (if agent saved despite instructions)\n",
    "if not final_plan and write_tool_content:\n",
    "    final_plan, plan_source = extract_plan_from_write_tool(write_tool_content)\n",
    "\n",
    "# Priority 3: Claude's internal plan directory (safety net)\n",
    "if not final_plan:\n",
    "    final_plan, plan_source = extract_plan_from_claude_dir()\n",
    "\n",
    "# Report results\n",
    "if final_plan:\n",
    "    print(f\"✅ Plan extracted from: {plan_source}\")\n",
    "    print(f\"   Plan length: {len(final_plan):,} characters\")\n",
    "\n",
    "    # Save to file\n",
    "    plan_file = save_plan_to_file(\n",
    "        plan_content=final_plan,\n",
    "        plan_source=plan_source,\n",
    "        model_name=MODEL,\n",
    "        prompt_summary=\"Restructure our engineering team for AI focus.\",\n",
    "    )\n",
    "    print(f\"\\n📁 Plan saved to: {plan_file}\")\n",
    "else:\n",
    "    error_msg = \"Could not extract plan content from any source!\\n\"\n",
    "    error_msg += \"   Sources checked: message stream, Write tool, ~/.claude/plans/\"\n",
    "    if write_tool_paths:\n",
    "        error_msg += f\"\\n   Write tool attempted to save to: {write_tool_paths}\"\n",
    "    print(f\"❌ ERROR: {error_msg}\")\n",
    "    raise RuntimeError(f\"Plan extraction failed: {error_msg}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Engineering Restructure Plan</div><p>I've provided the complete engineering team restructuring plan directly in my response within the <code>&lt;plan&gt;</code> tags as requested. The plan includes:</p>\n",
       "<ul>\n",
       "<li><strong>Team structure changes</strong> - From 25 to 29 engineers with 2 new AI-focused teams</li>\n",
       "<li><strong>Hiring roadmap</strong> - 6 new hires over 8 months, prioritized by criticality</li>\n",
       "<li><strong>Internal transfers</strong> - 4 engineers upskilled from existing teams</li>\n",
       "<li><strong>12-month timeline</strong> - Phased implementation with clear milestones</li>\n",
       "<li><strong>Budget analysis</strong> - Monthly burn increases from ~$380K to ~$537K</li>\n",
       "<li><strong>Success metrics</strong> - Concrete KPIs for 6 and 12-month checkpoints</li>\n",
       "<li><strong>Risk mitigation</strong> - Key risks identified with mitigation strategies</li>\n",
       "</ul>\n",
       "<p>Ready to proceed when you've reviewed the plan!</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Display the plan result with styled HTML\n",
    "display_agent_response(messages, title=\"Engineering Restructure Plan\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Executing the Saved Plan\n",
    "\n",
    "As mentioned above, the agent will stop after creating its plan. The saved plan file serves as a review artifact for stakeholders.\n",
    "\n",
    "**To execute the plan after review:**\n",
    "1. Review the saved plan in `chief_of_staff_agent/plans/plan_*.md`\n",
    "2. If approved, send a new query with `continue_conversation=True` and remove `permission_mode=\"plan\"` to execute\n",
    "\n",
    "This workflow enables a \"plan → review → approve → execute\" cycle, perfect for high-stakes decisions like organizational restructuring or major infrastructure changes."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### How Plan Persistence Works\n",
    "\n",
    "In the code above, we implemented a **robust multi-source plan capture mechanism** that handles the various ways Plan Mode agents may output their plans:\n",
    "\n",
    "**The Challenge:**\n",
    "When using `permission_mode=\"plan\"`, the agent may output the plan in different ways:\n",
    "1. **Direct text output** in the message stream (ideal case)\n",
    "2. **Write tool** to save to `~/.claude/plans/` (Claude's internal plan system)\n",
    "3. **Write tool** to save to a custom path\n",
    "\n",
    "Our capture mechanism handles all three scenarios with a **priority-based fallback system**:\n",
    "\n",
    "**Source Priority (in order):**\n",
    "\n",
    "1. **Message Stream** (Preferred)\n",
    "   - Capture text blocks from `msg.content` during streaming\n",
    "   - Extract content between `<plan></plan>` XML tags\n",
    "   - This is the cleanest approach as content comes directly from the response\n",
    "\n",
    "2. **Write Tool Capture**\n",
    "   - Monitor for Write tool calls in the message stream\n",
    "   - Extract the `content` parameter being written\n",
    "   - Useful when the agent decides to save despite prompt instructions\n",
    "\n",
    "3. **Claude's Internal Plan Directory**\n",
    "   - Check `~/.claude/plans/` for recently created plan files (within 5 minutes)\n",
    "   - Read and extract content from the most recent file\n",
    "   - Acts as a safety net when other methods fail\n",
    "\n",
    "4. **Full Content Fallback**\n",
    "   - If no XML tags found but substantial content exists (>500 chars), use it directly\n",
    "   - Prevents empty plan files while preserving partial information\n",
    "\n",
    "**Key Implementation Details:**\n",
    "\n",
    "```python\n",
    "def extract_plan_from_text(text):\n",
    "    \"\"\"Extract content between <plan> tags, return None if not found or empty.\"\"\"\n",
    "    match = re.search(r'<plan>(.*?)</plan>', text, re.DOTALL)\n",
    "    if match:\n",
    "        extracted = match.group(1).strip()\n",
    "        # Validate minimum content length (a real plan should be substantial)\n",
    "        if len(extracted) > 200:\n",
    "            return extracted\n",
    "    return None\n",
    "```\n",
    "\n",
    "**Why Content Validation Matters:**\n",
    "- Previous versions could produce empty plan files if extraction \"succeeded\" with no content\n",
    "- We now require a minimum of 200 characters for XML-tagged content\n",
    "- This prevents false positives where regex matches empty or trivial content\n",
    "\n",
    "**Prompt Engineering for Direct Output:**\n",
    "The prompt explicitly instructs the agent:\n",
    "- **DO NOT use the Write tool** - prevents file-system detours\n",
    "- **Output directly in response** - ensures content flows through message stream\n",
    "- **Use XML tags** - enables clean extraction from potentially verbose responses\n",
    "\n",
    "This approach gives you:\n",
    "- **Reliability**: Plans are captured regardless of agent behavior\n",
    "- **Transparency**: The saved file indicates which source was used\n",
    "- **Audit Trail**: History of all plans with timestamps and source metadata\n",
    "- **Debugging**: Clear error messages when extraction fails\n",
    "\n",
    "Let's view the saved plan:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "## 📋 Saved Plan Preview\n",
       "\n",
       "# TechStart Inc. Engineering Team Restructuring Plan for AI Focus\n",
       "\n",
       "## Executive Summary\n",
       "Restructure the 25-person engineering team to build AI/ML capabilities while maintaining core product development. This plan balances immediate hiring needs with internal upskilling and strategic reorganization over a 12-month period.\n",
       "\n",
       "---\n",
       "\n",
       "## Current State Assessment\n",
       "\n",
       "| Team | Headcount | Current Focus |\n",
       "|------|-----------|---------------|\n",
       "| Backend | 12 | Core product, APIs, infrastructure |\n",
       "| Frontend | 8 | Web/mobile interfaces |\n",
       "| DevOps | 5 | CI/CD, cloud infrastructure |\n",
       "| **Total** | **25** | |\n",
       "\n",
       "**Key Constraints:**\n",
       "- Monthly burn: ~$500K | Runway: 20 months\n",
       "- Senior Engineer comp: $180K-$220K + equity\n",
       "- Series A stage - need to show growth metrics\n",
       "\n",
       "---\n",
       "\n",
       "## Proposed Future State (Month 12)\n",
       "\n",
       "### New Team Structure\n",
       "\n",
       "| Team | Current | Future | Change |\n",
       "|------|---------|--------|--------|\n",
       "| Backend/Core | 12 | 8 | -4 |\n",
       "| Frontend | 8 | 6 | -2 |\n",
       "| DevOps/MLOps | 5 | 6 | +1 |\n",
       "| **AI/ML Platform** | 0 | 5 | +5 |\n",
       "| **AI Product** | 0 | 4 | +4 |\n",
       "| **Total** | **25** | **29** | **+4** |\n",
       "\n",
       "### New Teams Created\n",
       "\n",
       "**1. AI/ML Platform Team (5 engineers)**\n",
       "- Focus: Infrastructure, model training pipelines, ML tooling\n",
       "- Composition: 2 new hires (ML Engineers) + 2 internal transfers (Backend) + 1 internal (DevOps)\n",
       "- Lead: New hire - Senior ML Engineer ($200-220K)\n",
       "\n",
       "**2. AI Product Team (4 engineers)**\n",
       "- Focus: AI features, integrations, user-facing ML applications\n",
       "- Composition: 2 new hires (ML/AI specialists) + 1 internal (Backend) + 1 internal (Frontend)\n",
       "- Lead: Promoted internal senior engineer + AI upskilling\n",
       "\n",
       "---\n",
       "\n",
       "## Hiring Plan\n",
       "\n",
       "### New Positions (6 total new hires)\n",
       "\n",
       "| Role | Priority | Timeline | Comp Range | Notes |\n",
       "|------|----------|----------|------------|-------|\n",
       "| Senior ML Engineer (Lead) | P0 | Month 1-2 | $200-220K | Team lead, architecture |\n",
       "| ML Engineer | P0 | Month 2-3 | $180-200K | Platform focus |\n",
       "| ML Engineer | P1 | Month 3-4 | $180-200K | Product focus |\n",
       "| AI/ML Engineer | P1 | Month 4-5 | $170-190K | Generalist |\n",
       "| MLOps Engineer | P2 | Month 5-6 | $160-180K | DevOps + ML |\n",
       "| Junior ML Engineer | P2 | Month 6-8 | $130-150K | Growth hire |\n",
       "\n",
       "**Total New Hiring Cost:** ~$1.02-1.14M annually\n",
       "\n",
       "### Internal Transfers & Upskilling (4 engineers)\n",
       "\n",
       "| From Team | # Engineers | New Role | Training Investment |\n",
       "|-----------|-------------|----------|---------------------|\n",
       "| Backend | 3 | ML Platform/Product | $15K each (courses, certs) |\n",
       "| Frontend | 1 | AI Product (UI/UX) | $10K (AI tools training) |\n",
       "\n",
       "**Upskilling Budget:** ~$55K total\n",
       "\n",
       "---\n",
       "\n",
       "## Implementation Timeline\n",
       "\n",
       "### Phase 1: Foundation (Months 1-3)\n",
       "- [ ] Hire Senior ML Engineer (Team Lead) - **Critical first hire**\n",
       "- [ ] Identify 4 internal transfer candidates based on interest/aptitude\n",
       "- [ ] Begin ML upskilling program for transfer candidates\n",
       "- [ ] Set up ML infrastructure foundations (MLOps engineer involvement)\n",
       "- [ ] Define AI product roadmap with Product team\n",
       "\n",
       "### Phase 2: Team Formation (Months 4-6)\n",
       "- [ ] Complete core AI team hiring (4 of 6 hires)\n",
       "- [ ] Officially launch AI/ML Platform team\n",
       "- [ ] Internal transfers complete bootcamp/training\n",
       "- [ ] First AI feature POC delivered\n",
       "- [ ] MLOps practices integrated into DevOps workflow\n",
       "\n",
       "### Phase 3: Scaling (Months 7-9)\n",
       "- [ ] Complete remaining hires\n",
       "- [ ] AI Product team fully operational\n",
       "- [ ] First AI feature in production\n",
       "- [ ] Cross-team collaboration patterns established\n",
       "- [ ] Model monitoring and observability in place\n",
       "\n",
       "### Phase 4: Optimization (Months 10-12)\n",
       "- [ ] Team velocity optimization\n",
       "- [ ] Evaluate team composition effectiveness\n",
       "- [ ] Plan for next growth phase\n",
       "- [ ] Document AI development best practices\n",
       "\n",
       "---\n",
       "\n",
       "## Budget Impact Analysis\n",
       "\n",
       "### Monthly Cost Changes\n",
       "\n",
       "| Category | Current | Month 6 | Month 12 |\n",
       "|----------|---------|---------|----------|\n",
       "| Engineering Salaries | ~$375K | ~$430K | ~$485K |\n",
       "| Training/Upskilling | $0 | $9K | $2K |\n",
       "| AI Tools/Infrastructure | ~$5K | ~$20K | ~$35K |\n",
       "| Recruiting Costs | Variable | ~$40K | ~$15K |\n",
       "| **Monthly Total** | **~$380K** | **~$499K** | **~$537K** |\n",
       "\n",
       "### Annual Impact Summary\n",
       "- **Year 1 Additional Investment:** ~$900K-1.1M\n",
       "- **New Monthly Burn (Month 12):** ~$537K (+$37K from engineering growth)\n",
       "- **Runway Impact:** Reduces to ~17 months (still healthy for Series A)\n",
       "\n",
       "### ROI Considerations\n",
       "- AI features typically command 20-40% pricing premium in B2B SaaS\n",
       "- Competitive differentiation in market\n",
       "- Potential for AI-driven operational efficiencies\n",
       "\n",
       "---\n",
       "\n",
       "## Risk Mitigation\n",
       "\n",
       "| Risk | Likelihood | Impact | Mitigation |\n",
       "|------|------------|--------|------------|\n",
       "| Senior ML hire takes >3 months | Medium | High | Engage specialized recruiters early; consider contractor bridge |\n",
       "| Internal transfers struggle with ML | Low | Medium | Rigorous selection process; extended training runway |\n",
       "| AI projects don't deliver value | Medium | High | Start with high-impact, lower-complexity features |\n",
       "| Team culture friction | Low | Medium | Integrate teams gradually; shared goals and rituals |\n",
       "| Budget overrun | Medium | Medium | Phase hiring based on runway checks quarterly |\n",
       "\n",
       "---\n",
       "\n",
       "## Success Metrics\n",
       "\n",
       "### 6-Month Milestones\n",
       "- [ ] AI/ML Platform team fully staffed (5 engineers)\n",
       "- [ ] First AI-powered feature in beta\n",
       "- [ ] 4 internal engineers completed ML certification\n",
       "- [ ] ML infrastructure supporting model training/deployment\n",
       "\n",
       "### 12-Month Milestones\n",
       "- [ ] 2+ AI features in production\n",
       "- [ ] AI team velocity matches core team benchmarks\n",
       "- [ ] Customer NPS improvement attributable to AI features\n",
       "- [ ] 15%+ of product roadmap is AI-focused\n",
       "- [ ] Retention of transferred engineers >90%\n",
       "\n",
       "### KPIs to Track\n",
       "- Time-to-hire for ML roles\n",
       "- AI feature adoption rates\n",
       "- Model performance metrics (latency, accuracy)\n",
       "- Engineering velocity (story points/sprint) across teams\n",
       "- Employee satisfaction scores (especially transfers)\n",
       "\n",
       "---\n",
       "\n",
       "## Immediate Next Steps (Week 1-2)\n",
       "\n",
       "1. **Executive alignment** - Present plan to leadership for approval\n",
       "2. **Recruiter engagement** - Brief recruiting on Senior ML Engineer search\n",
       "3. **Internal survey** - Gauge interest in AI/ML roles among current engineers\n",
       "4. **Budget approval** - Finance sign-off on increased burn rate\n",
       "5. **Infrastructure assessment** - DevOps audit of ML infrastructure needs\n",
       "\n",
       "---\n",
       "\n",
       "## Organizational Chart (Future State)\n",
       "\n",
       "```\n",
       "VP Engineering\n",
       "├── Backend/Core Team (8)\n",
       "│   └── 2 squads × 4 engineers\n",
       "├── Frontend Team (6)\n",
       "│   └── 2 squads × 3 engineers\n",
       "├── DevOps/MLOps Team (6)\n",
       "│   └── 4 DevOps + 2 MLOps\n",
       "├── AI/ML Platform Team (5) [NEW]\n",
       "│   └── Lead + 4 engineers\n",
       "└── AI Product Team (4) [NEW]\n",
       "    └── Lead + 3 engineers\n",
       "```\n",
       "\n",
       "---\n",
       "\n",
       "*Plan prepared for TechStart Inc. Series A stage (~$10M raised, 20-month runway)*\n",
       "*Recommended review: Quarterly budget and hiring progress checkpoints*"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "📁 Full plan with metadata saved to: chief_of_staff_agent/plans/plan_20251204_152737.md\n"
     ]
    }
   ],
   "source": [
    "# Display the saved plan with markdown rendering\n",
    "from IPython.display import Markdown, display\n",
    "\n",
    "# Show the plan with proper markdown formatting\n",
    "display(Markdown(f\"## 📋 Saved Plan Preview\\n\\n{final_plan}\"))\n",
    "\n",
    "print(f\"\\n📁 Full plan with metadata saved to: {plan_file}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Advanced Features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 4: Custom Slash Commands\n",
    "\n",
    "> Note: slash commands are syntactic sugar for users, not new agent capabilities\n",
    "\n",
    "**What**: Custom slash commands are predefined prompt templates that users can trigger with shorthand syntax (e.g., `/budget-impact`). These are **user-facing shortcuts**, not agent capabilities. Think of them as keyboard shortcuts that expand into full, well-crafted prompts.\n",
    "\n",
    "**Why**: Your Chief of Staff will handle recurring executive questions. Instead of users typing complex prompts repeatedly, they can use already vetted prompts. This improves consistency and standardization.\n",
    "\n",
    "**How**:\n",
    "- Define a markdown file in `.claude/commands/`. For example, we defined one in `.claude/commands/slash-command-test.md`. Notice how the command is defined: frontmatter with two fields (name, description) and the expanded prompt with an option to include arguments passed on in the query.\n",
    "- You can add parameters to your prompt using `$ARGUMENTS` (for full argument string) or `$1`, `$2`, etc. (for positional arguments)\n",
    "- The user uses the slash command in their prompt\n",
    "\n",
    "> **CRITICAL SDK CONFIGURATION**: When using the SDK, you **must** set `setting_sources=[\"project\"]` in your `ClaudeAgentOptions` for slash commands to work. By default, the SDK operates in isolation mode and does NOT load filesystem settings (slash commands, CLAUDE.md, subagents, hooks, etc.). This is different from using Claude Code interactively where these are loaded automatically."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Thinking...\n"
     ]
    }
   ],
   "source": [
    "# User types: \"/slash-command-test this is a test\"\n",
    "# -> behind the scenes EXPANDS to the prompt in .claude/commands/slash-command-test.md\n",
    "# In this case the expanded prompt says to simply reverse the sentence word wise\n",
    "\n",
    "messages = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        cwd=\"chief_of_staff_agent\",\n",
    "        # IMPORTANT: setting_sources must include \"project\" to load slash commands from .claude/commands/\n",
    "        # Without this, the SDK does NOT load filesystem settings (slash commands, CLAUDE.md, etc.)\n",
    "        setting_sources=[\"project\"],\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\"/slash-command-test this is a test\")\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages.append(msg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Slash Command Result</div><p>The sentence \"this is a test\" reversed word-wise is:</p>\n",
       "<p><strong>test a is this</strong></p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display_agent_response(messages, title=\"Slash Command Result\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 5: Hooks - Automated Deterministic Actions\n",
    "\n",
    "**What**: Hooks are Python scripts that you can set to execute automatically, among other events, before (pre) or after (post) specific tool calls. Hooks run **deterministically**, making them perfect for validation and audit trails.\n",
    "\n",
    "**Why**: Imagine scenarios where you want to make sure that your agent has some guardrails (e.g., prevent dangerous operations) or when you want to have an audit trail. Hooks are ideal in combination with agents to allow them enough freedom to achieve their task, while still making sure that the agents behave in a safe way.\n",
    "\n",
    "**How**:\n",
    "- Define hook scripts in `.claude/hooks/` -> _what_ is the behaviour that should be executed when a hook is triggered\n",
    "- Define hook configuration in `.claude/settings.local.json` -> _when_ should a hook be triggered\n",
    "- In this case, our hooks are configured to watch specific tool calls (Bash, Write, Edit)\n",
    "- When those tools are called, the hook script runs after the tool completes (PostToolUse)\n",
    "\n",
    "> **SDK CONFIGURATION NOTE**: Hooks configured in `.claude/settings.local.json` require `setting_sources=[\"project\", \"local\"]`. The SDK distinguishes between three setting sources:\n",
    "> - `\"project\"` → `.claude/settings.json` (version-controlled, team-shared)\n",
    "> - `\"local\"` → `.claude/settings.local.json` (gitignored, local settings like hooks)\n",
    "> - `\"user\"` → `~/.claude/settings.json` (global user settings)\n",
    ">\n",
    "> Since our hooks are in `settings.local.json`, we must include `\"local\"` in `setting_sources`.\n",
    "\n",
    "**Example: Report Tracking for Compliance**\n",
    "\n",
    "A hook to log Write/Edit operations on financial reports for audit and compliance purposes.\n",
    "The hook is defined in `chief_of_staff_agent/.claude/hooks/report-tracker.py` and the logic that enforces it is in `chief_of_staff_agent/.claude/settings.local.json`:\n",
    "\n",
    "\n",
    "```json\n",
    "\"hooks\": {\n",
    "  \"PostToolUse\": [\n",
    "    {\n",
    "      \"matcher\": \"Write\",\n",
    "      \"hooks\": [\n",
    "        {\n",
    "          \"type\": \"command\",\n",
    "          \"command\": \"$CLAUDE_PROJECT_DIR/.claude/hooks/report-tracker.py\"\n",
    "        }\n",
    "      ]\n",
    "    },\n",
    "    {\n",
    "      \"matcher\": \"Edit\",\n",
    "      \"hooks\": [\n",
    "        {\n",
    "          \"type\": \"command\",\n",
    "          \"command\": \"$CLAUDE_PROJECT_DIR/.claude/hooks/report-tracker.py\"\n",
    "        }\n",
    "      ]\n",
    "    }\n",
    "  ]\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Using: Bash()\n",
      "🤖 Using: Bash()\n",
      "🤖 Using: Bash()\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Bash()\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n",
      "🤖 Using: Write()\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Q2 Financial Forecast</div><p>I've created a comprehensive Q2 Financial Forecast Report and saved it to the output_reports folder. Here's a summary of what's included:</p>\n",
       "<h2>Report Summary</h2>\n",
       "<p><strong>📊 Q2 2024 Financial Forecast Report Created</strong></p>\n",
       "<p><strong>Location:</strong> <code>/output_reports/Q2_2024_Financial_Forecast_Report.md</code></p>\n",
       "<h3>Key Highlights:</h3>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Metric</th>\n",
       "<th>Value</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td><strong>Cash in Bank</strong></td>\n",
       "<td>$10M</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Current Runway</strong></td>\n",
       "<td>20 months (until Sept 2025)</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Monthly Burn</strong></td>\n",
       "<td>$500K gross / ~$260K net</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Q2 Total Net Burn</strong></td>\n",
       "<td>$740K</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>ARR</strong></td>\n",
       "<td>$2.4M (15% MoM growth)</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<h3>Positive Trends:</h3>\n",
       "<ul>\n",
       "<li>✅ Net burn <strong>decreasing</strong> 9.6% month-over-month (from $260K → $235K)</li>\n",
       "<li>✅ Revenue growth (20.8%) <strong>outpacing</strong> burn increase (5%)</li>\n",
       "<li>✅ Revenue per employee improving 14%</li>\n",
       "</ul>\n",
       "<h3>Planning Scenarios:</h3>\n",
       "<ul>\n",
       "<li><strong>Conservative</strong>: 38-month runway (if revenue holds flat)</li>\n",
       "<li><strong>With 10 new engineers</strong>: ~15-month runway</li>\n",
       "<li><strong>Base case with growth</strong>: Path to break-even by Q2 2025</li>\n",
       "</ul>\n",
       "<p>The report includes detailed monthly breakdowns, hiring cost impact analysis, revenue milestones, risk assessment, and strategic recommendations for Series B timing.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "messages = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        cwd=\"chief_of_staff_agent\",\n",
    "        allowed_tools=[\"Bash\", \"Write\", \"Edit\", \"MultiEdit\"],\n",
    "        # IMPORTANT: setting_sources must include BOTH \"project\" AND \"local\" to load hooks\n",
    "        # - \"project\" loads .claude/settings.json (shared settings, CLAUDE.md, slash commands)\n",
    "        # - \"local\" loads .claude/settings.local.json (where hooks are configured)\n",
    "        setting_sources=[\"project\", \"local\"],\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\n",
    "        \"Create a quick Q2 financial forecast report with our current burn rate and runway projections. Save it to our /output_reports folder.\"\n",
    "    )\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages.append(msg)\n",
    "\n",
    "# The hook will track this in audit/report_history.json\n",
    "display_agent_response(messages, title=\"Q2 Financial Forecast\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you now navigate to `./chief_of_staff_agent/audit/report_history.json`, you will find that it has logged that the agent has created and/or made changes to your report. The generated report itself you can find at `./chief_of_staff_agent/output_reports/`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Feature 6: Subagents via Task Tool\n",
    "\n",
    "**What**: The Task tool enables your agent to delegate specialized work to other subagents. These subagents each have their own instructions, tools, and expertise.\n",
    "\n",
    "**Why**: Adding subagents opens up a lot of possibilities:\n",
    "1. Specialization: each subagent is an expert in their domain\n",
    "2. Separate context: subagents have their own conversation history and tools\n",
    "3. Parallellization: multiple subagents can work simultaneously on different aspects.\n",
    "\n",
    "**How**:\n",
    "- Add `\"Task\"` to allowed_tools\n",
    "- Use a system prompt to instruct your agent how to delegate tasks (you can also define this its CLAUDE.md more generally)\n",
    "- Create a markdown file for each agent in `.claude/agents/`. For example, check the one for `.claude/agents/financial-analyst.md` and notice how a (sub)agent can be defined with such an easy and intuitive markdown file: frontmatter with three fields (name, description, and tools) and its system prompt. The description is useful for the main chief of staff agent to know when to invoke each subagent.\n",
    "\n",
    "**Visualization Enhancements**: Our `print_activity()` and `visualize_conversation()` utilities have been enhanced to clearly show subagent operations:\n",
    "- 🚀 indicates when a subagent is being delegated to (with the subagent name)\n",
    "- 📎 indicates tools being used BY the subagent (indented for visual hierarchy)\n",
    "- Visual separators clearly mark subagent delegation and completion boundaries\n",
    "- Task descriptions and prompts are shown in the conversation timeline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Thinking...\n",
      "🚀 Delegating to subagent: financial-analyst\n",
      "   └─ Task: Analyze 5 engineer hiring impact\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Using: Bash()\n",
      "   📎 [financial-analyst] Using: Read()\n",
      "   📎 [financial-analyst] Using: Read()\n",
      "   ✓ Tool completed\n",
      "   ✓ Tool completed\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Using: Read()\n",
      "   📎 [financial-analyst] Using: Bash()\n",
      "   ✓ Tool completed\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Using: Bash()\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Using: Bash()\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Using: Bash()\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Using: Bash()\n",
      "   ✓ Tool completed\n",
      "   ✓ Tool completed\n",
      "   📎 [financial-analyst] Thinking...\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       ".pretty-card {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    border: 2px solid transparent;\n",
       "    border-radius: 14px;\n",
       "    padding: 14px 16px;\n",
       "    margin: 10px 0;\n",
       "    background: linear-gradient(#fff, #fff) padding-box,\n",
       "                linear-gradient(135deg, #3b82f6, #9333ea) border-box;\n",
       "    color: #111;\n",
       "    box-shadow: 0 4px 12px rgba(0,0,0,.08);\n",
       "}\n",
       ".pretty-title {\n",
       "    font-weight: 700;\n",
       "    margin-bottom: 8px;\n",
       "    font-size: 14px;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card pre,\n",
       ".pretty-card code {\n",
       "    background: #f3f4f6;\n",
       "    color: #111;\n",
       "    padding: 8px;\n",
       "    border-radius: 8px;\n",
       "    display: block;\n",
       "    overflow-x: auto;\n",
       "    font-size: 13px;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       ".pretty-card img {\n",
       "    max-width: 100%;\n",
       "    height: auto;\n",
       "    border-radius: 8px;\n",
       "}\n",
       "/* Tables: both pandas (.pretty-table) and markdown-rendered */\n",
       ".pretty-card table {\n",
       "    border-collapse: collapse;\n",
       "    width: 100%;\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card th,\n",
       ".pretty-card td {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    padding: 6px 8px;\n",
       "    text-align: left;\n",
       "}\n",
       ".pretty-card th {\n",
       "    background: #f9fafb;\n",
       "    font-weight: 600;\n",
       "}\n",
       "/* Markdown headings */\n",
       ".pretty-card h1, .pretty-card h2, .pretty-card h3, .pretty-card h4 {\n",
       "    margin: 0.5em 0 0.3em 0;\n",
       "    color: #111;\n",
       "}\n",
       ".pretty-card h1 { font-size: 1.4em; }\n",
       ".pretty-card h2 { font-size: 1.2em; }\n",
       ".pretty-card h3 { font-size: 1.1em; }\n",
       "/* Markdown lists and paragraphs */\n",
       ".pretty-card ul, .pretty-card ol {\n",
       "    margin: 0.5em 0;\n",
       "    padding-left: 1.5em;\n",
       "}\n",
       ".pretty-card p {\n",
       "    margin: 0.5em 0;\n",
       "}\n",
       ".pretty-card hr {\n",
       "    border: none;\n",
       "    border-top: 1px solid #e5e7eb;\n",
       "    margin: 1em 0;\n",
       "}\n",
       "</style>\n",
       "<div class=\"pretty-card\"><div class=\"pretty-title\">Hiring Impact Analysis</div><h2>Financial Impact Analysis: Hiring 5 Engineers</h2>\n",
       "<h3>Executive Summary</h3>\n",
       "<p><strong>Recommendation: ✅ PROCEED WITH CAUTION</strong> - Use a staged hiring approach with 3 Senior + 2 Junior engineers</p>\n",
       "<hr />\n",
       "<h3>Financial Impact at a Glance</h3>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Metric</th>\n",
       "<th>Current</th>\n",
       "<th>After 5 Hires</th>\n",
       "<th>Change</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td><strong>Monthly Burn</strong></td>\n",
       "<td>$500,000</td>\n",
       "<td>$575,833</td>\n",
       "<td>+15.2%</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Runway</strong></td>\n",
       "<td>20 months</td>\n",
       "<td>17.1 months</td>\n",
       "<td>-2.9 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Headcount</strong></td>\n",
       "<td>50</td>\n",
       "<td>55</td>\n",
       "<td>+10%</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Engineering %</strong></td>\n",
       "<td>50%</td>\n",
       "<td>54.5%</td>\n",
       "<td>+4.5%</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<p><strong>One-time costs:</strong> ~$165K (recruiting + onboarding)</p>\n",
       "<hr />\n",
       "<h3>Three Scenarios Analyzed</h3>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Scenario</th>\n",
       "<th>Mix</th>\n",
       "<th>New Monthly Burn</th>\n",
       "<th>New Runway</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td><strong>A (Recommended)</strong></td>\n",
       "<td>3 Senior + 2 Junior</td>\n",
       "<td>$575,833</td>\n",
       "<td>17.1 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td>B</td>\n",
       "<td>5 Senior</td>\n",
       "<td>$591,665</td>\n",
       "<td>16.6 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td>C</td>\n",
       "<td>2 Senior + 3 Junior</td>\n",
       "<td>$567,917</td>\n",
       "<td>17.3 months</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<hr />\n",
       "<h3>Why This Works ✅</h3>\n",
       "<ol>\n",
       "<li><strong>Strong Revenue Growth</strong> - 15% MoM ARR growth ($2.4M → projected $5.5M by Dec 2024) partially offsets increased burn</li>\n",
       "<li><strong>Healthy Runway Post-Hire</strong> - 17+ months exceeds the minimum 12-month threshold</li>\n",
       "<li><strong>Series B Alignment</strong> - Maintains sufficient runway to close Series B (target Q1 2026)</li>\n",
       "<li><strong>Strategic Necessity</strong> - Product launch and European expansion require engineering capacity</li>\n",
       "</ol>\n",
       "<h3>Key Risks ⚠️</h3>\n",
       "<ol>\n",
       "<li><strong>Runway Compression</strong> - 2.9-month reduction leaves less buffer</li>\n",
       "<li><strong>Series B Dependency</strong> - Must close by Q1 2026 (reduced negotiating flexibility)</li>\n",
       "<li><strong>Revenue Assumptions</strong> - Projections depend on continued 15% MoM growth</li>\n",
       "</ol>\n",
       "<hr />\n",
       "<h3>Recommended Implementation Plan</h3>\n",
       "<p><strong>Phase 1 (Immediate):</strong> Hire 3 engineers (2 Senior + 1 Junior)<br />\n",
       "<strong>Phase 2 (30-60 days later):</strong> Hire remaining 2 engineers (1 Senior + 1 Junior)</p>\n",
       "<p><strong>Financial Guardrails:</strong><br />\n",
       "- Maintain minimum 15-month runway at all times<br />\n",
       "- Pause hiring if revenue growth drops below 12% MoM<br />\n",
       "- Begin Series B conversations by August 2024</p>\n",
       "<hr />\n",
       "<h3>Bottom Line</h3>\n",
       "<p>The hire is <strong>financially prudent</strong> given your strong growth trajectory and healthy runway buffer. However, it's critical to:<br />\n",
       "1. Execute staged hiring to de-risk<br />\n",
       "2. Maintain revenue momentum<br />\n",
       "3. Stay on track with Series B timeline</p>\n",
       "<p><strong>Confidence Level: 75%</strong> — Proceed, but with active monitoring and clear guardrails.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Reset the subagent tracking context before starting a new query\n",
    "# This ensures clean state for activity display\n",
    "reset_activity_context()\n",
    "\n",
    "messages = []\n",
    "async with ClaudeSDKClient(\n",
    "    options=ClaudeAgentOptions(\n",
    "        model=MODEL,\n",
    "        allowed_tools=[\"Task\"],  # this enables our Chief agent to invoke subagents\n",
    "        system_prompt=\"Delegate financial questions to the financial-analyst subagent. Do not try to answer these questions yourself.\",\n",
    "        cwd=\"chief_of_staff_agent\",\n",
    "        setting_sources=[\"project\", \"local\"],\n",
    "    )\n",
    ") as agent:\n",
    "    await agent.query(\"Should we hire 5 engineers? Analyze the financial impact.\")\n",
    "    async for msg in agent.receive_response():\n",
    "        print_activity(msg)\n",
    "        messages.append(msg)\n",
    "\n",
    "display_agent_response(messages, title=\"Hiring Impact Analysis\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    \n",
       "<style>\n",
       ".conversation-timeline {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    max-width: 900px;\n",
       "    margin: 1em 0;\n",
       "}\n",
       ".timeline-header {\n",
       "    background: linear-gradient(135deg, #3b82f6, #9333ea);\n",
       "    color: white;\n",
       "    padding: 12px 16px;\n",
       "    border-radius: 12px 12px 0 0;\n",
       "    font-weight: 700;\n",
       "    font-size: 14px;\n",
       "}\n",
       ".timeline-body {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    border-top: none;\n",
       "    border-radius: 0 0 12px 12px;\n",
       "    padding: 12px;\n",
       "    background: #fafafa;\n",
       "}\n",
       ".msg-block {\n",
       "    margin: 8px 0;\n",
       "    padding: 10px 12px;\n",
       "    border-radius: 8px;\n",
       "    background: white;\n",
       "    border-left: 3px solid #e5e7eb;\n",
       "}\n",
       ".msg-block.system { border-left-color: #6b7280; }\n",
       ".msg-block.assistant { border-left-color: #3b82f6; }\n",
       ".msg-block.tool { border-left-color: #10b981; background: #f0fdf4; }\n",
       ".msg-block.subagent { border-left-color: #9333ea; background: #faf5ff; }\n",
       ".msg-block.result { border-left-color: #f59e0b; background: #fffbeb; }\n",
       ".msg-label {\n",
       "    font-size: 11px;\n",
       "    font-weight: 600;\n",
       "    text-transform: uppercase;\n",
       "    color: #6b7280;\n",
       "    margin-bottom: 4px;\n",
       "}\n",
       ".msg-content {\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "}\n",
       ".msg-content pre {\n",
       "    background: #f3f4f6;\n",
       "    padding: 8px;\n",
       "    border-radius: 6px;\n",
       "    overflow-x: auto;\n",
       "    font-size: 12px;\n",
       "}\n",
       ".tool-list {\n",
       "    display: flex;\n",
       "    flex-wrap: wrap;\n",
       "    gap: 6px;\n",
       "    margin-top: 4px;\n",
       "}\n",
       ".tool-badge {\n",
       "    background: #e0f2fe;\n",
       "    color: #0369a1;\n",
       "    padding: 2px 8px;\n",
       "    border-radius: 4px;\n",
       "    font-size: 11px;\n",
       "    font-family: monospace;\n",
       "}\n",
       ".stats-bar {\n",
       "    display: flex;\n",
       "    gap: 16px;\n",
       "    padding: 10px 12px;\n",
       "    background: #f9fafb;\n",
       "    border-radius: 8px;\n",
       "    font-size: 12px;\n",
       "    color: #374151;\n",
       "    margin-top: 8px;\n",
       "}\n",
       ".stat-item { display: flex; gap: 4px; }\n",
       ".stat-label { color: #6b7280; }\n",
       "</style>\n",
       "\n",
       "    <div class=\"conversation-timeline\">\n",
       "        <div class=\"timeline-header\">🤖 Agent Conversation Timeline • claude-opus-4-5</div>\n",
       "        <div class=\"timeline-body\">\n",
       "            <div class=\"msg-block system\"><div class=\"msg-label\">⚙️ System</div><div class=\"msg-content\">Initialized (bf3bc346...)</div></div><div class=\"msg-block assistant\"><div class=\"msg-label\">🤖 Assistant</div><div class=\"msg-content\"><p>I'll delegate this financial analysis to the financial-analyst subagent who can properly analyze the impact of hiring 5 engineers.</p></div></div><div class=\"msg-block subagent\"><div class=\"msg-label\">🚀 Subagent: financial-analyst</div><div class=\"msg-content\">Analyze 5 engineer hiring impact</div></div><div class=\"msg-block tool\"><div class=\"msg-label\">🔧 Tools</div><div class=\"tool-list\"><span class=\"tool-badge\">Bash</span><span class=\"tool-badge\">Read: burn_rate.csv</span><span class=\"tool-badge\">Read: revenue_forecast.json</span><span class=\"tool-badge\">Read: hiring_costs.csv</span><span class=\"tool-badge\">Bash</span><span class=\"tool-badge\">Bash</span><span class=\"tool-badge\">Bash</span><span class=\"tool-badge\">Bash</span><span class=\"tool-badge\">Bash</span></div></div><div class=\"msg-block assistant\"><div class=\"msg-label\">🤖 Assistant</div><div class=\"msg-content\"><h2>Financial Impact Analysis: Hiring 5 Engineers</h2>\n",
       "<h3>Executive Summary</h3>\n",
       "<p><strong>Recommendation: ✅ PROCEED WITH CAUTION</strong> - Use a staged hiring approach with 3 Senior + 2 Junior engineers</p>\n",
       "<hr />\n",
       "<h3>Financial Impact at a Glance</h3>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Metric</th>\n",
       "<th>Current</th>\n",
       "<th>After 5 Hires</th>\n",
       "<th>Change</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td><strong>Monthly Burn</strong></td>\n",
       "<td>$500,000</td>\n",
       "<td>$575,833</td>\n",
       "<td>+15.2%</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Runway</strong></td>\n",
       "<td>20 months</td>\n",
       "<td>17.1 months</td>\n",
       "<td>-2.9 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Headcount</strong></td>\n",
       "<td>50</td>\n",
       "<td>55</td>\n",
       "<td>+10%</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Engineering %</strong></td>\n",
       "<td>50%</td>\n",
       "<td>54.5%</td>\n",
       "<td>+4.5%</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<p><strong>One-time costs:</strong> ~$165K (recruiting + onboarding)</p>\n",
       "<hr />\n",
       "<h3>Three Scenarios Analyzed</h3>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Scenario</th>\n",
       "<th>Mix</th>\n",
       "<th>New Monthly Burn</th>\n",
       "<th>New Runway</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td><strong>A (Recommended)</strong></td>\n",
       "<td>3 Senior + 2 Junior</td>\n",
       "<td>$575,833</td>\n",
       "<td>17.1 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td>B</td>\n",
       "<td>5 Senior</td>\n",
       "<td>$591,665</td>\n",
       "<td>16.6 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td>C</td>\n",
       "<td>2 Senior + 3 Junior</td>\n",
       "<td>$567,917</td>\n",
       "<td>17.3 months</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<hr />\n",
       "<h3>Why This Works ✅</h3>\n",
       "<ol>\n",
       "<li><strong>Strong Revenue Growth</strong> - 15% MoM ARR growth ($2.4M → projected $5.5M by Dec 2024) partially offsets increased burn</li>\n",
       "<li><strong>Healthy Runway Post-Hire</strong> - 17+ months exceeds the minimum 12-month threshold</li>\n",
       "<li><strong>Series B Alignment</strong> - Maintains sufficient runway to close Series B (target Q1 2026)</li>\n",
       "<li><strong>Strategic Necessity</strong> - Product launch and European expansion require engineering capacity</li>\n",
       "</ol>\n",
       "<h3>Key Risks ⚠️</h3>\n",
       "<ol>\n",
       "<li><strong>Runway Compression</strong> - 2.9-month reduction leaves less buffer</li>\n",
       "<li><strong>Series B Dependency</strong> - Must close by Q1 2026 (reduced negotiating flexibility)</li>\n",
       "<li><strong>Revenue Assumptions</strong> - Projections depend on continued 15% MoM growth</li>\n",
       "</ol>\n",
       "<hr />\n",
       "<h3>Recommended Implementation Plan</h3>\n",
       "<p><strong>Phase 1 (Immediate):</strong> Hire 3 engineers (2 Senior + 1 Junior)<br />\n",
       "<strong>Phase 2 (30-60 days later):</strong> Hire remaining 2 engineers (1 Senior + 1 Junior)</p>\n",
       "<p><strong>Financial Guardrails:</strong><br />\n",
       "- Maintain minimum 15-month runway at all times<br />\n",
       "- Pause hiring if revenue growth drops below 12% MoM<br />\n",
       "- Begin Series B conversations by August 2024</p>\n",
       "<hr />\n",
       "<h3>Bottom Line</h3>\n",
       "<p>The hire is <strong>financially prudent</strong> given your strong growth trajectory and healthy runway buffer. However, it's critical to:<br />\n",
       "1. Execute staged hiring to de-risk<br />\n",
       "2. Maintain revenue momentum<br />\n",
       "3. Stay on track with Series B timeline</p>\n",
       "<p><strong>Confidence Level: 75%</strong> — Proceed, but with active monitoring and clear guardrails.</p></div></div><div class=\"msg-block result\"><div class=\"msg-label\">✅ Complete</div><div class=\"stats-bar\"><span class=\"stat-item\"><span class=\"stat-label\">Turns:</span> 2</span> <span class=\"stat-item\"><span class=\"stat-label\">Tokens:</span> 1,173</span> <span class=\"stat-item\"><span class=\"stat-label\">Cost:</span> $0.28</span> <span class=\"stat-item\"><span class=\"stat-label\">Duration:</span> 164.9s</span></div></div>\n",
       "        </div>\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "visualize_conversation(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, when our main agent decides to use a subagent, it will:\n",
    "  1. Call the Task tool with parameters like:\n",
    "  ```json\n",
    "    {\n",
    "      \"description\": \"Analyze hiring impact\",\n",
    "      \"prompt\": \"Analyze the financial impact of hiring 5 engineers...\",\n",
    "      \"subagent_type\": \"financial-analyst\"\n",
    "    }\n",
    "  ```\n",
    "  2. The Task tool executes the subagent in a separate context\n",
    "  3. Return results to main Chief of Staff agent to continue processing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Putting It All Together"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now put everything we've seen together. We will ask our agent to determine the financial impact of hiring 3 senior engineers and write their insights to `output_reports/hiring_decision.md`. This demonstrates all the features seen above:\n",
    "- **Bash Tool**: Used to execute the `hiring_impact.py` script to determine the impact of hiring new engineers\n",
    "- **Memory**: Reads `CLAUDE.md` in directory as context to understand the current budgets, runway, revenue and other relevant information\n",
    "- **Output style**: Different output styles, defined in `chief_of_staff_agent/.claude/output-styles`\n",
    "- **Custom Slash Commands**: Uses the shortcut `/budget-impact` that expands to full prompt defined in `chief_of_staff_agent/.claude/commands`\n",
    "- **Subagents**: Our `/budget_impact` command guides the chief of staff agent to invoke the financial-analyst subagent defined in `chief_of_staff_agent/.claude/agents` \n",
    "- **Hooks**: Hooks are defined in `chief_of_staff_agent/.claude/hooks` and configured in `chief_of_staff_agent/.claude/settings.local.json`\n",
    "    - If one of our agents is updating the financial report, the hook should log this edit/write activity in the `chief_of_staff_agent/audit/report_history.json` logfile\n",
    "    - If the financial analyst subagent will invoke the `hiring_impact.py` script, this will be logged in `chief_of_staff_agent/audit/tool_usage_log.json` logfile\n",
    "\n",
    "- **Plan Mode**: If you want the chief of staff to come up with a plan for you to approve before taking any action, uncomment the commented line below\n",
    "\n",
    "To have this ready to go, we have encapsulated the agent loop in a python file, similar to what we did in the previous notebook. Check out the agent.py file in the `chief_of_staff_agent` subdirectory. \n",
    "\n",
    "All in all, our `send_query()` function takes in 4 parameters (prompt, continue_conversation, permission_mode, and output_style), everything else is set up in the agent file, namely: system prompt, max turns, allowed tools, and the working directory.\n",
    "\n",
    "To better visualize how this all comes together, check out these [flow and architecture diagrams that Claude made for us :)](./chief_of_staff_agent/flow_diagram.md)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "🤖 Thinking...\n",
      "🤖 Using: Glob()\n",
      "🤖 Using: Glob()\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n",
      "🤖 Using: Task()\n",
      "✓ Tool completed\n",
      "🤖 Using: Bash()\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "🤖 Using: Read()\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n",
      "🤖 Using: Write()\n",
      "✓ Tool completed\n",
      "🤖 Thinking...\n"
     ]
    }
   ],
   "source": [
    "from chief_of_staff_agent.agent import send_query\n",
    "\n",
    "reset_activity_context()\n",
    "\n",
    "result, messages = await send_query(\n",
    "    \"/budget-impact hiring 3 senior engineers. Save your insights by updating the 'hiring_decision.md' file in /output_reports or creating a new file there\",\n",
    "    # permission_mode=\"plan\", # Enable this to use planning mode\n",
    "    output_style=\"executive\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    \n",
       "<style>\n",
       ".conversation-timeline {\n",
       "    font-family: ui-sans-serif, system-ui;\n",
       "    max-width: 900px;\n",
       "    margin: 1em 0;\n",
       "}\n",
       ".timeline-header {\n",
       "    background: linear-gradient(135deg, #3b82f6, #9333ea);\n",
       "    color: white;\n",
       "    padding: 12px 16px;\n",
       "    border-radius: 12px 12px 0 0;\n",
       "    font-weight: 700;\n",
       "    font-size: 14px;\n",
       "}\n",
       ".timeline-body {\n",
       "    border: 1px solid #e5e7eb;\n",
       "    border-top: none;\n",
       "    border-radius: 0 0 12px 12px;\n",
       "    padding: 12px;\n",
       "    background: #fafafa;\n",
       "}\n",
       ".msg-block {\n",
       "    margin: 8px 0;\n",
       "    padding: 10px 12px;\n",
       "    border-radius: 8px;\n",
       "    background: white;\n",
       "    border-left: 3px solid #e5e7eb;\n",
       "}\n",
       ".msg-block.system { border-left-color: #6b7280; }\n",
       ".msg-block.assistant { border-left-color: #3b82f6; }\n",
       ".msg-block.tool { border-left-color: #10b981; background: #f0fdf4; }\n",
       ".msg-block.subagent { border-left-color: #9333ea; background: #faf5ff; }\n",
       ".msg-block.result { border-left-color: #f59e0b; background: #fffbeb; }\n",
       ".msg-label {\n",
       "    font-size: 11px;\n",
       "    font-weight: 600;\n",
       "    text-transform: uppercase;\n",
       "    color: #6b7280;\n",
       "    margin-bottom: 4px;\n",
       "}\n",
       ".msg-content {\n",
       "    font-size: 13px;\n",
       "    color: #111;\n",
       "}\n",
       ".msg-content pre {\n",
       "    background: #f3f4f6;\n",
       "    padding: 8px;\n",
       "    border-radius: 6px;\n",
       "    overflow-x: auto;\n",
       "    font-size: 12px;\n",
       "}\n",
       ".tool-list {\n",
       "    display: flex;\n",
       "    flex-wrap: wrap;\n",
       "    gap: 6px;\n",
       "    margin-top: 4px;\n",
       "}\n",
       ".tool-badge {\n",
       "    background: #e0f2fe;\n",
       "    color: #0369a1;\n",
       "    padding: 2px 8px;\n",
       "    border-radius: 4px;\n",
       "    font-size: 11px;\n",
       "    font-family: monospace;\n",
       "}\n",
       ".stats-bar {\n",
       "    display: flex;\n",
       "    gap: 16px;\n",
       "    padding: 10px 12px;\n",
       "    background: #f9fafb;\n",
       "    border-radius: 8px;\n",
       "    font-size: 12px;\n",
       "    color: #374151;\n",
       "    margin-top: 8px;\n",
       "}\n",
       ".stat-item { display: flex; gap: 4px; }\n",
       ".stat-label { color: #6b7280; }\n",
       "</style>\n",
       "\n",
       "    <div class=\"conversation-timeline\">\n",
       "        <div class=\"timeline-header\">🤖 Agent Conversation Timeline • claude-opus-4-5</div>\n",
       "        <div class=\"timeline-body\">\n",
       "            <div class=\"msg-block system\"><div class=\"msg-label\">⚙️ System</div><div class=\"msg-content\">Initialized (cea37adf...)</div></div><div class=\"msg-block assistant\"><div class=\"msg-label\">🤖 Assistant</div><div class=\"msg-content\"><p>I'll analyze the budget impact of hiring 3 senior engineers. Let me first check the current financial data and existing reports, then delegate to the financial analyst for a comprehensive analysis.</p></div></div><div class=\"msg-block tool\"><div class=\"msg-label\">🔧 Tools</div><div class=\"tool-list\"><span class=\"tool-badge\">Glob</span><span class=\"tool-badge\">Glob</span><span class=\"tool-badge\">Read: hiring_costs.csv</span><span class=\"tool-badge\">Read: burn_rate.csv</span><span class=\"tool-badge\">Read: revenue_forecast.json</span><span class=\"tool-badge\">Read: hiring_decision.md</span></div></div><div class=\"msg-block assistant\"><div class=\"msg-label\">🤖 Assistant</div><div class=\"msg-content\"><p>I see there's already an existing analysis. Let me delegate to the financial analyst subagent to provide an updated, comprehensive analysis with the latest data and additional insights.</p></div></div><div class=\"msg-block subagent\"><div class=\"msg-label\">🚀 Subagent: financial-analyst</div><div class=\"msg-content\">Analyze hiring 3 senior engineers budget impact</div></div><div class=\"msg-block tool\"><div class=\"msg-label\">🔧 Tools</div><div class=\"tool-list\"><span class=\"tool-badge\">Bash</span><span class=\"tool-badge\">Read: hiring_costs.csv</span><span class=\"tool-badge\">Read: burn_rate.csv</span><span class=\"tool-badge\">Read: revenue_forecast.json</span></div></div><div class=\"msg-block assistant\"><div class=\"msg-label\">🤖 Assistant</div><div class=\"msg-content\"><p>Excellent! The financial analyst has provided a comprehensive analysis. Let me now update the hiring decision report with this enhanced analysis.</p></div></div><div class=\"msg-block tool\"><div class=\"msg-label\">🔧 Tools</div><div class=\"tool-list\"><span class=\"tool-badge\">Write</span></div></div><div class=\"msg-block assistant\"><div class=\"msg-label\">🤖 Assistant</div><div class=\"msg-content\"><p>I've completed the comprehensive budget impact analysis for hiring 3 senior engineers. Here's a summary of the key findings:</p>\n",
       "<hr />\n",
       "<h2>Budget Impact Analysis Summary</h2>\n",
       "<h3>Recommendation: <strong>CONDITIONAL APPROVAL WITH STAGGERED APPROACH</strong></h3>\n",
       "<h3>Key Financial Impact</h3>\n",
       "<table>\n",
       "<thead>\n",
       "<tr>\n",
       "<th>Metric</th>\n",
       "<th>Current</th>\n",
       "<th>Post-Hiring</th>\n",
       "<th>Change</th>\n",
       "</tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr>\n",
       "<td>Monthly Gross Burn</td>\n",
       "<td>$525K</td>\n",
       "<td>$590K</td>\n",
       "<td>+$65K (+12.4%)</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td>Monthly Net Burn</td>\n",
       "<td>$235K</td>\n",
       "<td>$300K</td>\n",
       "<td>+$65K (+27.7%)</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td>Cash Runway</td>\n",
       "<td>42.6 months</td>\n",
       "<td>32.9 months</td>\n",
       "<td>-9.7 months</td>\n",
       "</tr>\n",
       "<tr>\n",
       "<td><strong>Break-Even</strong></td>\n",
       "<td>-</td>\n",
       "<td><strong>November 2024</strong></td>\n",
       "<td>5 months</td>\n",
       "</tr>\n",
       "</tbody>\n",
       "</table>\n",
       "<h3>Total Investment</h3>\n",
       "<ul>\n",
       "<li><strong>One-time costs:</strong> $129,000 (recruiting, onboarding, equipment)</li>\n",
       "<li><strong>Annual recurring:</strong> $780,000 ($65K/month loaded)</li>\n",
       "<li><strong>First year total:</strong> $909,000</li>\n",
       "</ul>\n",
       "<h3>Why Proceed?</h3>\n",
       "<ol>\n",
       "<li><strong>Break-even achievable in 5 months</strong> with current 15% MoM revenue growth</li>\n",
       "<li><strong>Strong runway buffer</strong> - 32.9 months even without revenue growth</li>\n",
       "<li><strong>Strategic timing</strong> aligns with Q2 product launch and market opportunity</li>\n",
       "</ol>\n",
       "<h3>Risk Mitigation Strategy</h3>\n",
       "<ul>\n",
       "<li><strong>Staggered hiring</strong> (1 engineer/month) reduces integration risk</li>\n",
       "<li><strong>Milestone gates</strong> allow pause/abort if revenue growth slows</li>\n",
       "<li><strong>Series B prep</strong> should begin immediately to strengthen position</li>\n",
       "</ul>\n",
       "<h3>Critical Success Factors</h3>\n",
       "<ol>\n",
       "<li>Maintain &gt;12% MoM revenue growth</li>\n",
       "<li>Hire Engineering Manager concurrent with first engineer</li>\n",
       "<li>Begin Series B conversations now</li>\n",
       "<li>Complete stock refresh for key engineer retention</li>\n",
       "</ol>\n",
       "<p>The full analysis has been saved to <code>/output_reports/hiring_decision.md</code> with detailed sections on ROI analysis, 4 alternative options, 8 risk factors with mitigations, implementation timeline, and success metrics.</p></div></div><div class=\"msg-block result\"><div class=\"msg-label\">✅ Complete</div><div class=\"stats-bar\"><span class=\"stat-item\"><span class=\"stat-label\">Turns:</span> 9</span> <span class=\"stat-item\"><span class=\"stat-label\">Tokens:</span> 5,871</span> <span class=\"stat-item\"><span class=\"stat-label\">Cost:</span> $0.48</span> <span class=\"stat-item\"><span class=\"stat-label\">Duration:</span> 279.1s</span></div></div>\n",
       "        </div>\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "visualize_conversation(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "We've demonstrated how the Claude Code SDK enables you to build sophisticated multi-agent systems with enterprise-grade features. Starting from basic script execution with the Bash tool, we progressively introduced advanced capabilities including persistent memory with CLAUDE.md, custom output styles for different audiences, strategic planning mode, slash commands for user convenience, compliance hooks for guardrailing, and subagent coordination for specialized tasks.\n",
    "\n",
    "By combining these features, we created an AI Chief of Staff capable of handling complex executive decision-making workflows. The system delegates financial analysis to specialized subagents, maintains audit trails through hooks, adapts communication styles for different stakeholders, and provides actionable insights backed by data-driven analysis.\n",
    "\n",
    "This foundation in advanced agentic patterns and multi-agent orchestration prepares you for building production-ready enterprise systems. In the next notebook, we'll explore how to connect our agents to external services through Model Context Protocol (MCP) servers, dramatically expanding their capabilities beyond the built-in tools.\n",
    "\n",
    "Next: [02_The_observability_agent.ipynb](02_The_observability_agent.ipynb) - Learn how to extend your agents with custom integrations and external data sources through MCP."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "cc-sdk-tutorial",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
